package org.xebia.roo.addon.openshift;

import java.io.File;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Logger;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.shell.CliCommand;
import org.springframework.roo.shell.CliOption;
import org.springframework.roo.shell.CommandMarker;
import org.springframework.roo.shell.Shell;
import org.springframework.roo.shell.converters.StaticFieldConverter;

import com.openshift.express.client.IApplication;
import com.openshift.express.client.ICartridge;
import com.openshift.express.client.IOpenShiftService;
import com.openshift.express.client.InvalidCredentialsOpenShiftException;
import com.openshift.express.client.OpenShiftEndpointException;
import com.openshift.express.internal.client.InternalUser;

@Component
@Service
public class OpenshiftCommands implements CommandMarker { // All command types
															// must implement
															// the CommandMarker
															// interface
	private Logger log = Logger.getLogger(getClass().getName());

	@Reference
	private StaticFieldConverter staticFieldConverter;

	@Reference
	Shell shell;

	@Reference
	ProjectOperations projectOperations;

	private static final int MAX_WAIT = 500;

	protected void activate(ComponentContext context) {
		staticFieldConverter.add(OpenshiftPropertyName.class);
	}

	protected void deactivate(ComponentContext context) {
		staticFieldConverter.remove(OpenshiftPropertyName.class);
	}

	@CliCommand(value = "rhc deploy", help = "Deploys code")
	public void deploy() {
		shell.executeCommand("! git add .");
		shell.executeCommand("! git commit -a -m \"deploy\"");
		shell.executeCommand("! git push");
	}

	@CliCommand(value = "rhc create app", help = "Creates Application")
	public void create(
			@CliOption(key = "applicationName", mandatory = true) String applicationName,
			@CliOption(key = "rhLogin", mandatory = true) String rhLogin,
			@CliOption(key = "password", mandatory = true) String password)
			throws Exception {
		internalInstall(applicationName, rhLogin, password);
	}

	private boolean internalInstall(String applicationName, String rhLogin,
			String password) throws Exception {

		String baseUrl = Util.getDefaultBaseUrl();

		// Wipe the singleton
		IOpenShiftService openshift = OpenShiftServiceFactory.create(baseUrl);
		IApplication application = null;
		try {
			application = openshift.createApplication(applicationName,
					ICartridge.JBOSSAS_7, new InternalUser(rhLogin, password,
							openshift));
		} catch (InvalidCredentialsOpenShiftException e) {
			log.info("\nInvalid user credentials.  Please check your Red Hat login and password and try again.\n");
			return false;
		} catch (OpenShiftEndpointException e) {
			log.info("OpenShift failed to create the application");
			log.info(e.getMessage());
			if (e.getCause().getClass() != null)
				log.info(e.getCause().getMessage());
			return false;
		}

		shell.executeCommand("! git init");
		log.info("Initialized Git Repository");
		
		
//		String rootPath = projectOperations.getPathResolver().getRoot();
//		log.info("Root Path :" + rootPath);
//		File file = new File(rootPath);
//		File[] files = file.listFiles();
//		for (File dir : files) {
//			if (dir.isDirectory()) {
//				if (!dir.getName().equals(".git")) {
//					shell.executeCommand("! git init");
//					log.info("Initialized Git Repository");
//				}
//			}
//		}

		log.info("Waiting for OpenShift to propagate DNS");
		if (!waitForExpress(application.getApplicationUrl())) {
			log.info("OpenShift did not propagate DNS properly");
			return false;
		}
		
		shell.executeCommand("! git remote add openshift -f "+ application.getGitUri());

		log.info("Application deployed to " + application.getApplicationUrl());

		return true;
	}

	private boolean waitForExpress(String url) {
		for (int i = 0; i < MAX_WAIT; i++) {
			try {
				if (i % 5 == 0)
					log.info("Trying to contact " + url + " (attempt "
							+ (i + 1) + " of " + MAX_WAIT + ")");
				HttpURLConnection connection = (HttpURLConnection) new URL(url)
						.openConnection();
				if (connection.getResponseCode() == HttpURLConnection.HTTP_OK)
					return true;
			} catch (Exception e) {

			}
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				Thread.currentThread().interrupt();
			}
		}
		return false;
	}

}